﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeanboxSoftware.BeanMap
{
  public interface IMap<K, V> : IDictionary<K, V>
  {
    V Get(K key);

    //V this[K k] { get; set; } // promised with IDictionary
    //bool ContainsKey(K k); // promised with IDictionary

    new void Add(K key, V value);
    new void Add(KeyValuePair<K, V> item);
    new bool Contains(KeyValuePair<K, V> item);
    new bool Remove(KeyValuePair<K, V> item);
    new IEnumerable<K> Keys { get; }
    new IEnumerable<V> Values { get; }
    IEnumerable<KeyValuePair<K, V>> KeyValues { get; }
  }

  public interface IMap<K1, K2, V> : IDictionary<K1, IDictionary<K2, V>>
  {
    IMap<K2, V> Get(K1 key1);
    V Get(Tuple<K1, K2> key);
    V Get(K1 key1, K2 key2);

    new IMap<K2, V> this[K1 k1] { get; }
    V this[K1 k1, K2 k2] { get; set; }

    new IEnumerator<KeyValuePair<Tuple<K1, K2>, V>> GetEnumerator(); //foreach
    IEnumerable<KeyValuePair<Tuple<K1, K2>, V>> KeyValues { get; }
    new IEnumerable<Tuple<K1, K2>> Keys { get; }
    new IEnumerable<V> Values { get; }

    bool Remove(K1 k1, K2 k2);

    bool ContainsKey(Tuple<K1, K2> key);
    bool ContainsKey(K1 k1, K2 k2);
    //bool ContainsKey(K1 k1); // promised with IDictionary
  }

  public interface IMap<K1, K2, K3, V> : IDictionary<K1, IDictionary<K2, IDictionary<K3, V>>>
  {
    IMap<K2, K3, V> Get(K1 key);
    IMap<K3, V> Get(Tuple<K1, K2> key);
    IMap<K3, V> Get(K1 key1, K2 key2);
    V Get(Tuple<K1, K2, K3> key);
    V Get(K1 key1, K2 key2, K3 key3);

    new IMap<K2, K3, V> this[K1 k1] { get; }
    IMap<K3, V> this[K1 k1, K2 k2] { get; }
    V this[K1 k1, K2 k2, K3 k3] { get; set; }

    new IEnumerator<KeyValuePair<Tuple<K1, K2, K3>, V>> GetEnumerator(); //foreach
    IEnumerable<KeyValuePair<Tuple<K1, K2, K3>, V>> KeyValues { get; }
    new IEnumerable<Tuple<K1, K2, K3>> Keys { get; }
    new IEnumerable<V> Values { get; }

    bool Remove(K1 k1, K2 k2);
    bool Remove(K1 k1, K2 k2, K3 k3);

    bool ContainsKey(Tuple<K1, K2, K3> key);
    bool ContainsKey(Tuple<K1, K2> key);

    bool ContainsKey(K1 k1, K2 k2, K3 k3);
    bool ContainsKey(K1 k1, K2 k2);
    //bool ContainsKey(K1 k1); // promised with IDictionary

    //int Count { get; } // promised with IDictionary
    //void Clear(); // promised with IDictionary
    //bool Remove(K1 key); // promised with IDictionary
    //bool TryGetValue(K1 key, out IDictionary<K2, IDictionary<K3, V>> value); // promised with IDictionary
  }
}
